Transcrição
A aplicação que estamos utilizando para trabalhar com Webpack é o protótipo de um single page application. Nós sabemos que é normal utilizar frameworks do mercado em aplicações deste tipo, como Angular e React.
No entanto, existe algo que devemos considerar. Você percebeu que todos os módulos da aplicação ficarão no bundle.js, ou seja, em um único arquivo? Isto significa que se a aplicação tiver muitos módulos, o bundle.js vai ficar imenso.
No entanto, isto não é bom. Nós evitamos o problema de fazer múltiplas requisições para fazermos o download de vários arquivos. Mas, agora, gastamos um bom tempo para baixar o bundle.js e para só então, ele será processado pela aplicação.
Um estratégia utilizada para a resolução de problemas como esse é o code splitting (separação de código) e o lazy loading (carregamento preguiçoso). Em aplicação como AngularJS ou VueJS, em seus sistemas de rotas, podemos informar que queremos carregar um módulo no momento em que for necessário.
A aplicação não será carregada com esse módulo, ele ficará em back-end separado, e quando acessarmos o módulo pela primeira vez, ele será carregado pelo framework uma única vez.
Desta forma, se queremos fazer um carregamento sob demanda (lazy loading), devemos ter a aplicação divida em partes menores. Para o escopo do projeto, vamos escolher esse módulo - que define a classe NegociacaoService.js - para ser a parte carregada sob demanda.
Com isso, o Webpack saberá que no momento da criação dos
bundles, será gerado um arquivobundlepara a aplicação e outro separado destinado ao módulo carregado sob demanda.
Estes conceitos serão utilizados se você trabalha com AngularJS e React, ainda que existam alguns detalhes específicos de quando estes fazem o lazy loading. Mas é isso que faremos basicamente.
Primeiramente, levaremos em conta que não deve haver na nossa aplicação um import estático do módulo NegociacaoService. Sabemos que nesta aplicação, temos o index.js dentro de domain. Neste arquivo, estamos exportando o NegociacoesService.js:
export * from './negociacao/Negociacao.js';
export * from './negociacao/NegociacaoDao.js';
export * from './negociacao/NegociacaoService.js';
export * from './negociacao/Negociacoes.js';
Esta é uma técnica que chamamos de barrel. Nós removeremos o export referente ao NegociacaoService, depois, faremos o mesmo em NegociacaoController.js. No caso, dentro do primeiro import:
import { Negociacoes, Negociacao } from '../domain';
import { NegociacoesView, MensagemView, Mensagem, DateConverter } from '../ui';
import { getNegociacaoDao, Bind, getExceptionMessage, debounce, controller, bindEvent } from '../util';
Vamos removê-lo porque apagaremos todas as importações estáticas do módulo realizadas em nossa aplicação. Como retiramos o import, removeremos também o atributo service responsável pela criação da instância de NegociacaoService(). Logo abaixo do this._mensagem, removeremos this._service.
this._service = new NegociacaoService();
Em seguida, no método importaNegociacoes(), acessamos o service apesar de não existir mais a propriedade da classe, logo, teremos que criar a variável. A seguir, nós usaremos o destructuring do ECMAScript 6 para importar o NegociacaoService, que receberá o resultado de await System.import(). E dentro dos parênteses, passaremos o caminho do módulo.
@bindEvent('click', '#botao-importa')
@debounce()
async importaNegociacoes() {
try {
const { NegociacaoService } = await System.import('../domain/negociacao/NegociacaoService');
const service = new NegociacaoService();
const negociacoes = await service.obtemNegociacoesDoPeriodo();
console.log(negociacoes);
negociacoes.filter(novaNegociacao =>
!this._negociacoes.paraArray().some(negociacaoExistente =>
novaNegociacao.equals(negociacaoExistente)))
.forEach(negociacao => this._negociacoes.adiciona(negociacao));
this._mensagem.texto = 'Negociações do período importadas com sucesso';
} catch (err) {
this._mensagem.texto = getExceptionMessage(err);
}
}
Adicionamos ainda ao try, const service.
Como o projeto utilizou o ES8, utilizamos o async await, com isso podemos chamar um método que seja assíncrono, e esperar o seu resultado.
Se você quer se aprofundar nesta sintaxe, pode fazer o curso de Typescript da Alura.
Agora é possível realizar o carregamento "preguiçoso", com o System.import() - que é disponibilizado pelo Webpack. Você pode se perguntar sobre a maneira como estamos fazendo lazy loading do módulo NegociacaoService. Ele será carregado pela primeira vez, em seguida, será utilizado pela variável, depois, quando chamarmos o mesmo método, o módulo não será mais recarregado e o System.import não será feito novamente.
Porém, como será feita a separação por bundles diferentes?
Se fizermos o build de desenvolvimento no Terminal, o Webpack criará dois novos arquivos dentro da pasta dist: bundle.js e 0.bundle.js.

No arquivo 0.bundle.js, encontraremos o módulo que será carregado primeiramente, por meio do lazy loading. Ao perceber que está sendo realizada a importação dinâmica do módulo, o Webpack sabe quem deverá ser isolado no novo bundle, gerando o código perfeito.
Feito isso, não precisamos nos preocupar em importar o arquino no index.html. Após rodarmos o comando npm start no Terminal, veremos que a aplicação está rodando normalmente. Se abrirmos o Inspect e acessarmos a aba "Network", na primeira vez que a página for carregada, o arquivo 0.bundle.js não será listado. Em seguida, quando clicarmos no botão "Importar Negociações", o arquivo já será baixado na aplicação.

Esta forma de fazer carregamento preguiçoso e com códigos separados é bastante adotada em single pages applications. O sucesso do funcionamento dos frameworks depende do bom uso do Webpack.